package org.mte.sakn.properties;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * PropertiesHandlerImpl
 * 
 * @author Marco Traversari
 * @version $Revision: 1.2 $ $Date: 2011-04-20 08:34:19 $
 */
public class PropertiesHandlerImpl implements PropertiesHandler, Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8614207407020181087L;
	
	
	/**
	 * Oggetto <code>Properties</code> principale in cui viene caricato
	 * il file di properties.
	 */
	protected Properties props = null;
	
	/**
	 * PropertieHandlerImpl
	 */
	public PropertiesHandlerImpl() {		
	}
	
	/**
	 * Costruttore con il percorso del file di properties
	 * da leggere.
	 *
	 * @param filePath
	 * @throws IOException
	 */
	public PropertiesHandlerImpl(String filePath) throws IOException {
		loadFile(filePath);
	}
	
	/**
	 * Restituisce l'oggetto <code>Properties</code> instanziato.
	 *
	 * @return un oggetto di tipo <code>Properties</code>.
	 */
	public Properties getProperties() {
		return props;
	}

    /**
     * Imposta un oggetto di tipo <code>Properties</code>.
     *
     * @param props oggetto da impostare.
     */
	public void setProperties(Properties props) {
		this.props = props;
	}
	
	/**
	 * Restituisce il valore della chiave definita nel file di <i>properties</i>.
	 * Se la chiave non è trovata restituisce <code>null</code>, in caso contrario
	 * al valore vengono eliminati gli spazi bianchi.
	 *
	 * @param key � la chiave di una valore del file di <i>properties</i>.
	 *
	 * @return il valore associato alla chiave specificata.
	 */
	public String getString(String key) {
		String value = props.getProperty(key);
		value = (value != null) ? value.trim() : value;
		return value;
	}

	/**
	 * Restituisce il valore della chiave definita nel file di <i>properties</i>.
	 *
	 * @param key è la chiave di una valore del file di <i>properties</i>.
	 * @param defaultValue è il valore restituito se la chiave non è trovata.
	 *
	 * @return il valore associato alla chiave specificata.
	 */
	public String getString(String key, String defaultValue) {
		String value = props.getProperty(key, defaultValue);
		value = (value != null) ? value.trim() : value;
		return value;
	}
	
    /**
	 * <p>Restituisce un oggetto di tipo <code>Boolean</code> istanziato
     * con il valore del file di properties.</p>
	 * <p>Ci si aspetta che la chiave passata in input corrisponda ad un
	 * valore tipo <i>yes,no</i>,  <i>true,false</i>, <i>1,0</i> .</p>
	 *
	 * @param key la chiave per la quale serve il valore.
	 *
	 * @return <code>true</code> o <code>false</code> secondo il valore letto.
     */
	public Boolean getBoolean(String key) {
		return new Boolean(getBoolean(key, ""));
	}

    /**
	 * <p>Restituisce un oggetto di tipo <code>Boolean</code> istanziato
     * con il valore del file di properties.</p>
	 * <p>Ci si aspetta che la chiave passata in input corrisponda ad un
	 * valore tipo <i>yes,no</i>,  <i>true,false</i>, <i>1,0</i> .</p>
	 * <p>E' possibile passare una valore <i>default</i> nel caso
	 * che la chiave non è trovata.</p>
	 *
	 * @param key la chiave per la quale serve il valore.
	 * @param booleanValue valore di <i>default</i> se la chiave non � trovata.
	 *
	 * @return <code>true</code> o <code>false</code> secondo il valore letto.
     */
	public Boolean getBoolean(String key, String defaultValue) {
		String value = props.getProperty(key, defaultValue).trim();
		boolean isTrue = (value.equals("yes") || value.equals("true") || value.equals("1")) ? true : false;
		return isTrue;
	}
	
	/**
	 * Utilizza <code>getInteger(String key, int intDefaultValue)</code>.
	 * con <code>intDefaultValue = -1</code>.
	 *
	 * @param key è la chiave di una valore del file di <i>properties</i>.
	 *
	 * @return un tipo <code>Integer</code> che rappresenta il valore associato
	 * 				alla chiave specificata.
	 */
	public Integer getInteger(String key) {
		return getInteger(key, -1);
	}
	
	/**
	 * Restituisce il valore della chiave definita nel file di <i>properties</i>,
	 * trasformandolo in un <code>Integer</code> se il valore non � trovato ritorna il valore
	 * di default specificato.
	 *
	 * @param key è la chiave di una valore del file di <i>properties</i>.
	 * @param intDefaultValue è il valore di default ritornato nel caso che
	 * 			la chiave sia <code>null</code>.
	 *
	 * @return un tipo <code>int</code> che rappresenta il valore associato
	 * 				alla chiave specificata.
	 */
	public Integer getInteger(String key, Integer intDefaultValue) {
		String value = props.getProperty(key);
		Integer integerValue = (value != null) ? Integer.valueOf(value.trim()) : intDefaultValue;
		return integerValue;
	}
	
	/**
	 * <p>Riempie un ArrayList con valori presenti nell'oggetto
	 * properties caratterizzati da un chiave che ha una base fissa
	 * e un indice</p>
	 * <p>Es: baseKey=item</p>
	 * <ul>
	 * <li>item.0=value-0</li>
	 * <li>...</li>
	 * <li>item.n=value-n</li>
	 * </ul>
	 * @param baseKey
	 * @return values
	 */
	public List<String> getList(String baseKey) {
		ArrayList<String> values = null;
		String value = null;
		int pos = 0;
		while ((value = (String) props.get(baseKey + "." + pos)) != null) {
			if (values == null) {
				values = new ArrayList<String>();
			}
			values.add(value);
			pos++;
		}
		return values;
	}

	
    /**
	 * Legge un file di properties.
	 *
	 * @param filePath percorso assolut del file di properties.
	 * @throws IOException.
	 */
   	public void loadFile(String filePath) throws IOException {
		BufferedInputStream bufferedInputStream = null;
		if (props == null) {
			props = new Properties();
		}
		bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
		props.load(bufferedInputStream);
		bufferedInputStream.close();
	}

   	
	/**
	 * Legge un file di properties presente nel classpath.
     *
	 * @param filePath percorso relativo del classpath del file di properties.
	 * @throws IOException.
	 */
	public void loadResource(String filePath) throws IOException {
		if (props == null) {
			props = new Properties();
		}
		InputStream inputStream = getClass().getResourceAsStream(filePath);
		props.load(inputStream);
		inputStream.close();
	}
   	
}
